package api

import (
	"bufio"
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"log"
	"myproject/backend/types"
	"myproject/backend/utils"
	"net/http"
	"strconv"
	"sync"
	"time"

	"github.com/google/uuid"
	"github.com/gorilla/websocket"
)

type CameraApi struct {
	Ctx         context.Context
	clients     map[string]*CameraClient
	clientsLock sync.RWMutex
	serPort     *utils.SerialPort
}

func NewCameraApi(serPort *utils.SerialPort) *CameraApi {
	return &CameraApi{
		clients:     make(map[string]*CameraClient),
		clientsLock: sync.RWMutex{},
		serPort:     serPort,
	}
}

var upgrader = websocket.Upgrader{
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
}

// 检查摄像头是否可用
func (c *CameraApi) CheckCameraAvailability(deviceID int) types.JsResp {
	return types.JsResp{
		Resp: types.Resp{
			Code: 0,
			Msg:  "camera device is available",
		},
	}
}

func (s *CameraApi) Start(ctx context.Context) error {
	server := &http.Server{
		Addr:    ":8090",
		Handler: nil,
	}
	http.HandleFunc("/ws", s.initWebSocket)
	serverErr := make(chan error, 1)
	go func() {
		fmt.Println("WebSocket server starting on :8080")
		if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			serverErr <- err
		}
	}()
	select {
	case err := <-serverErr:
		return err
	case <-ctx.Done():
		shutdownCtx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
		defer cancel()
		if err := server.Shutdown(shutdownCtx); err != nil {
			return fmt.Errorf("shutdown error: %w", err)
		}
		fmt.Println("WebSocket server stopped")
		return nil
	}
}

func (s *CameraApi) initWebSocket(w http.ResponseWriter, r *http.Request) {
	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Println("WebSocket upgrade error:", err)
		return
	}
	cameraID := r.URL.Query().Get("camera_id")
	cameraType := r.URL.Query().Get("camera_type")
	if cameraType == "" {
		cameraType = "rgb"
	}
	if cameraID == "" {
		http.Error(w, "摄像头ID不能为空", http.StatusBadRequest)
		return
	}
	cameraId, err := strconv.Atoi(cameraID)
	if err != nil {
		fmt.Println("摄像头ID必须为整数")
		http.Error(w, "摄像头ID必须为整数", http.StatusBadRequest)
		return
	}
	fmt.Println("init WebSocket cameraID client:", cameraId)
	s.clientsLock.Lock()
	for _, client := range s.clients {
		if client.CameraID == cameraId && client.CameraType == cameraType && client.ConnActive {
			s.clientsLock.Unlock()
			log.Println("摄像头已被占用")
			http.Error(w, "摄像头已被占用", http.StatusBadRequest)
			return
		}
	}
	s.clientsLock.Unlock()
	cid := generateUUID()
	ctx, cancel := context.WithCancel(context.Background())
	client := &CameraClient{
		Conn:       conn,
		ConnActive: true,
		cameraLock: sync.Mutex{},
		cancel:     cancel,
		ctx:        ctx,
		CameraID:   cameraId,
		CameraType: cameraType,
	}
	s.clientsLock.Lock()
	s.clients[cid] = client
	s.clientsLock.Unlock()
	pingMsg := map[string]any{
		"pingInterval": 15,
		"pingTimeout":  30,
		"cid":          cid,
		"type":         "ping",
	}
	buf, _ := json.Marshal(pingMsg)
	if err := client.Conn.WriteMessage(websocket.TextMessage, buf); err != nil {
		client.ConnActive = false
		s.removerClient(cid)
		return
	}
	//go s.handleClientRead(cid, client)
	if cameraType == "tips" {
		go s.handleTipClientWrite(cid, client)
	} else {
		go s.handleClientWrite(cid, client)
	}
	fmt.Printf("init WebSocket client %s cameraID %s \n", cid, cameraID)
}

// 视频数据
//--frame\r\n
//Content-Type: image/jpeg\r\n\r\n
//jpegData
//\r\n

// 文本数据
// data:
// rawData\r\n\r\n
type FaceTips struct {
	TextAngle    string `json:"text_angle"`
	TextDistance string `json:"text_distance"`
}

func (s *CameraApi) handleTipClientWrite(cid string, client *CameraClient) {
	defer func() {
		s.removerClient(cid)
		fmt.Println("handleTipClientWrite close")
	}()
	videoClient := NewVideoTipsClient("http://127.0.0.1:8001")
	stream, err := videoClient.GetVideoStream()
	if err != nil {
		log.Println("获取视频流失败:", err)
		return
	}
	defer stream.Close()
	scanner := bufio.NewScanner(stream)

	buf := make([]byte, 0, 1024)
	scanner.Buffer(buf, cap(buf))
	scanner.Split(func(data []byte, atEOF bool) (advance int, token []byte, err error) {
		if i := bytes.Index(data, []byte("\r\n\r\n")); i >= 0 {
			return i + 4, data[:i], nil
		}
		return 0, nil, nil
	})
	for {
		select {
		case <-client.ctx.Done():
			return
		default:
			if !scanner.Scan() {
				if err := scanner.Err(); err != nil {
					log.Println("Scanner error:", err)
				}
				return
			}
			part := scanner.Bytes()
			prefix := []byte("data: ")
			if !bytes.HasPrefix(part, prefix) {
				continue // 忽略不符合格式的数据
			}
			jsonData := part[len(prefix):] // 提取纯 JSON 部分
			var tips FaceTips
			if err := json.Unmarshal(jsonData, &tips); err != nil {
				log.Println("JSON 解析失败:", err)
				continue
			}
			if err := client.Conn.WriteMessage(websocket.TextMessage, jsonData); err != nil {
				log.Println("Write header error:", err)
				return
			}
		}
	}
}

func (s *CameraApi) handleClientWrite(cid string, client *CameraClient) {
	defer func() {
		s.removerClient(cid)
		fmt.Println("handleClientWrite close")
	}()
	videoClient := NewVideoStreamClient("http://127.0.0.1:8001", client.CameraID)
	stream, err := videoClient.GetVideoStream()
	if err != nil {
		log.Println("获取视频流失败:", err)
		return
	}
	defer stream.Close()
	scanner := bufio.NewScanner(stream)

	buf := make([]byte, 0, 1024*1024)
	scanner.Buffer(buf, cap(buf))
	scanner.Split(func(data []byte, atEOF bool) (advance int, token []byte, err error) {
		// 按 --frame\r\n 分割
		if i := bytes.Index(data, []byte("--frame\r\n")); i >= 0 {
			return i + 9, data[:i], nil
		}
		return 0, nil, nil
	})
	for {
		select {
		case <-client.ctx.Done():
			return
		default:
			if !scanner.Scan() {
				if err := scanner.Err(); err != nil {
					log.Println("Scanner error:", err)
				}
				return
			}
			part := scanner.Bytes()
			idx := bytes.Index(part, []byte("\r\n\r\n"))
			if idx == -1 {
				continue
			}
			jpegData := part[idx+4:]
			if len(jpegData) == 0 {
				continue
			}
			//_ = client.Conn.SetWriteDeadline(time.Now().Add(5 * time.Second))
			//data := map[string]any{
			//	"type": "data",
			//	"data": len(jpegData),
			//}
			//dataJson, err := json.Marshal(data)
			//if err != nil {
			//	log.Println("JSON marshal error:", err)
			//	return
			//}
			//if err := client.Conn.WriteMessage(websocket.TextMessage, dataJson); err != nil {
			//	log.Println("Write header error:", err)
			//	return
			//}
			//// 发送帧数据
			//if err := client.Conn.WriteMessage(websocket.BinaryMessage, jpegData); err != nil {
			//	log.Println("Write frame error:", err)
			//	return
			//}
			if err := client.sendFrame(jpegData); err != nil {
				log.Println("Send frame error:", err)
				return
			}
		}
	}
}

func (s *CameraApi) handleClientRead(cid string, client *CameraClient) {
	defer func() {
		s.removerClient(cid)
		fmt.Println("handleClientRead close")
	}()
	for {
		select {
		case <-client.ctx.Done():
			fmt.Println("handleClientRead done")
			return
		default:
			_, _, err := client.Conn.ReadMessage()
			if err != nil {
				if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
					log.Printf("Read error: %v", err)
				}
				return
			}
		}
	}
}

func (s *CameraApi) StartCameraCapture() bool {
	resp := types.CameraStatus{}
	err := utils.HttpLocalRequest(utils.HttpRequestOptions{
		Method: "POST",
		Suffix: "/start",
		Resp:   &resp,
	})
	if err != nil {
		return false
	}
	if resp.Code != 0 {
		return false
	}
	fmt.Println("摄像头启动成功")
	return true
}

func (s *CameraApi) StopCameraCapture() {
	resp := types.CameraStatus{}
	err := utils.HttpLocalRequest(utils.HttpRequestOptions{
		Method: "POST",
		Suffix: "/stop",
		Resp:   &resp,
	})
	if err != nil {
		return
	}
	if resp.Code != 0 {
		return
	}
	log.Println("摄像头关闭成功")
	return
}

// 删除客户端信息
func (s *CameraApi) removerClient(cid string) {
	s.clientsLock.Lock()
	client, exists := s.clients[cid]
	if !exists {
		s.clientsLock.Unlock()
		return
	}
	delete(s.clients, cid)
	s.clientsLock.Unlock()
	s.safeCloseClient(client, cid)
}

func (s *CameraApi) safeCloseClient(client *CameraClient, cid string) {
	client.closeOnce.Do(func() {
		// 取消 context，通知所有相关协程
		if client.cancel != nil {
			client.cancel()
		}
		if client.Conn != nil {
			_ = client.Conn.Close()
		}
		client.ConnActive = false
		fmt.Printf("WebSocket client fully closed: %s (CameraID: %d)\n", cid, client.CameraID)
	})
}
func (s *CameraApi) StopCameraCaptureForClient(cid string) {
	fmt.Println("StopCameraCaptureForClient:", cid)
	s.removerClient(cid)
	return
}

func (s *CameraApi) FaceMeasurement(path string, depthPath string) types.CameraResponse {
	resp := types.CameraResponse{}
	body := map[string]any{
		"image_path": path,
		"depth_path": depthPath,
	}
	err := utils.HttpLocalRequest(utils.HttpRequestOptions{
		Method: "POST",
		Suffix: "/face-measure",
		Body:   body,
		Resp:   &resp,
	})
	if err != nil {
		return resp
	}
	return resp
}

func (s *CameraApi) GenerateFaceModels() types.FaceModelResponse {
	resp := types.FaceModelResponse{}
	err := utils.HttpLocalRequest(utils.HttpRequestOptions{
		Method: "POST",
		Suffix: "/generate_models",
		Resp:   &resp,
	})
	if err != nil {
		return resp
	}
	return resp
}

func (s *CameraApi) GlassMeasurement(path string, direction string) types.GlassMeasurements {
	resp := types.GlassMeasurements{}
	body := map[string]any{
		"front_distance":  270,
		"face_image_path": path,
		"face_direction":  direction,
	}
	err := utils.HttpLocalRequest(utils.HttpRequestOptions{
		Method: "POST",
		Suffix: "/glasses-measure",
		Body:   body,
		Resp:   &resp,
	})
	if err != nil {
		return resp
	}
	return resp
}

func (s *CameraApi) FrontGlassMeasurement(path string) types.FrontGlassMeasurements {
	resp := types.FrontGlassMeasurements{}
	body := map[string]any{
		"front_distance":  270,
		"face_image_path": path,
	}
	err := utils.HttpLocalRequest(utils.HttpRequestOptions{
		Method: "POST",
		Suffix: "/front-glasses-measure",
		Body:   body,
		Resp:   &resp,
	})
	if err != nil {
		return resp
	}
	return resp
}

func generateUUID() string {
	id := uuid.New().String()
	shortID := id[:8]
	return shortID
}

// 正脸第一张图片capturingFront
func (s *CameraApi) CameraCapture() types.CaptureResponse {
	resp := types.CaptureResponse{}
	err := utils.HttpLocalRequest(utils.HttpRequestOptions{
		Method: "POST",
		Suffix: "/capturingFront",
		Resp:   &resp,
	})
	if err != nil {
		resp.Code = -1
		return resp
	}
	return resp
}

func (s *CameraApi) CaptureWithGlass() types.CaptureWithGlassResponse {
	resp := types.CaptureWithGlassResponse{}
	err := utils.HttpLocalRequest(utils.HttpRequestOptions{
		Method: "POST",
		Suffix: "/capturingWithGlasses",
		Resp:   &resp,
	})
	if err != nil {
		resp.Code = -1
		return resp
	}
	return resp
}

// 向上移动点击
func (s *CameraApi) MoveUp() {
	s.serPort.Up()
}

// 向下移动点击
func (s *CameraApi) MoveDown() {
	s.serPort.Down()
}

// 停止摄像头 查看当前是否满足位置
func (s *CameraApi) MoveStop() types.LocalCommonResponse {
	s.serPort.Stop()
	fmt.Println("MoveStop")
	resp := types.LocalCommonResponse{}
	err := utils.HttpLocalRequest(utils.HttpRequestOptions{
		Method: "GET",
		Suffix: "/detection_results",
		Resp:   &resp,
	})
	if err != nil {
		resp.Code = -1
		return resp
	}
	return resp
}

func (s *CameraApi) OpenLight() {
	s.serPort.Light()
}

func (s *CameraApi) IsOnline() bool {
	return utils.IsOnline()
}
